﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Win32;
using System.Xml;
using System.Data.Common;
using ICSharpCode.SharpZipLib.Zip;
using System.ComponentModel;
using System.IO;
using ResourceBlender_Express.Properties;

namespace ResourceBlender_Express {
    /// <summary>
    /// Interaction logic for WinExport.xaml
    /// </summary>
    public partial class WinExport : Window {
        private Constants.DataType exportType;
        private BackgroundWorker worker;
        private WinProgress progress;
        private ApplicationSelector applicationSelector;

        public WinExport(Constants.DataType type) {
            InitializeComponent();
            this.exportType = type;
            lstType.SelectedValue = type.ToString().ToLower();
        }

        /// <summary>
        /// Adds the application selector and updates the application list.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void Window_Loaded(object sender, RoutedEventArgs e) {
            applicationSelector = new ApplicationSelector(ApplicationSelector.SelectionMode.SingleApplicationBundlesLanguages);
            applicationSelector.Mode = ApplicationSelector.SelectionMode.MultiApplicationBundlesLanguages;
            applicationSelector.PropertyChanged += (s, pe) => { TriggerUpdateFilename(null, null); };
            tbXMLXLS.Content = applicationSelector;
            ResourceBlenderCommands.UpdateFilename.Execute(null, this);
            lstType_SelectionChanged(this, null);
        }

        /// <summary>
        /// Shows the appropriate tab when the 'export type' listbox changes.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.SelectionChangedEventArgs"/> instance containing the event data.</param>
        private void lstType_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            if(!this.IsLoaded || lstType.SelectedValue == null)
                return;
            exportType = (Constants.DataType)Enum.Parse(typeof(Constants.DataType), lstType.SelectedValue.ToString(),true);
            switch(exportType) {
                case Constants.DataType.XML:
                    tbXML.IsSelected = true;
                    break;
                case Constants.DataType.XMLXLS:
                    tbXMLXLS.IsSelected = true;
                    break;
            }
            ResourceBlenderCommands.UpdateFilename.Execute(null, null);
        }

        /// <summary>
        /// Opens a dialog to browse for an export file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void BrowseForFile(object sender, ExecutedRoutedEventArgs e) {
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".xml";
            dlg.CheckPathExists = true;
            dlg.OverwritePrompt = true;
            dlg.FileName = txtFilename.Text;
            dlg.Title = "Save as...";
            dlg.Filter = "All files|*.*|Zip files (*.zip)|*.zip|XML files (*.xml)|*.xml";
            if(chkZip.IsChecked == true) {
                dlg.FilterIndex = 0;
            } else {
                switch(exportType) {
                    case Constants.DataType.XML:
                        dlg.FilterIndex = 2;
                        break;
                    case Constants.DataType.XMLXLS:
                        dlg.FilterIndex = 1;
                        break;
                }
            }
            if(dlg.ShowDialog() == true) {
                txtFilename.Text = dlg.FileName;
            }
        }

        /// <summary>
        /// Fires the UpdateFilename command
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void TriggerUpdateFilename(object sender, RoutedEventArgs e) {
            ResourceBlenderCommands.UpdateFilename.Execute(null, this);
        }

        /// <summary>
        /// Updates the filename to reflect the application selected.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void UpdateFilename(object sender, RoutedEventArgs e) {
            if(!this.IsLoaded) {
                return;
            }
            string fileName = string.Empty;
            switch(exportType) {
                case Constants.DataType.XML:
                    string extension = string.Empty;
                    if(chkZip.IsChecked == true) {
                        extension = ".zip";
                    } else {
                        extension = ".xml";
                    }
                    fileName = string.Format("ResourceBlender - {0}{1}", DateTime.Now.ToString("yyyy-MM-dd"), extension);
                    break;
                case Constants.DataType.XMLXLS:
                    if(applicationSelector.SelectedApplications.Count == 0)
                        return;
                    fileName = string.Format("{0} - {1}{2}", applicationSelector.SelectedApplications[0].DisplayName, DateTime.Now.ToString("yyyy-MM-dd"), chkZip.IsChecked == true ? ".zip" : ".xml");
                    break;
            }
            string path = Settings.Default.LastGenerationPath.Length > 0 ? Settings.Default.LastGenerationPath : Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            txtFilename.Text = System.IO.Path.Combine(path, fileName);
        }

        private void CanExecuteExport(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = worker == null || !worker.IsBusy;
        }

        /// <summary>
        /// Exports to the specified format.
        /// </summary>
        private void Export(object sender, ExecutedRoutedEventArgs e) {
            bool zipOutput = chkZip.IsChecked == true,
                 includeApps = chkApplications.IsChecked == true,
                 includeElements = chkElements.IsChecked == true,
                 includeResources = chkResources.IsChecked == true,
                 includeUsers = false,
                 includeTemplates = chkTemplates.IsChecked == true;
            string[] applicationIds = null,
                     selectedLanguages = null,
                     selectedBundles = null;
            if(!includeApps && !includeElements && !includeResources && !includeTemplates && !includeUsers) {
                DialogBox.ShowAlert(this, "Nothing selected to export", "Nothing To Export");
                return;
            }
            if(exportType == Constants.DataType.XMLXLS) {
                if(!applicationSelector.ValidateSelection(true)) {
                    return;
                } else {
                    applicationIds = (from app in applicationSelector.SelectedApplications select app.ID).ToArray();// new string[] { applicationSelector.SelectedApplication.ID };
                    selectedLanguages = applicationSelector.SelectedLanguages.Keys.ToArray();
                    selectedBundles = applicationSelector.SelectedBundles.Keys.ToArray();
                }
            }
            FileInfo outputFile = null;
            try {
                outputFile = new FileInfo(txtFilename.Text.Trim());
            } catch {
                DialogBox.Show(this, "Invalid filename", "Error", DialogBox.DialogBoxType.OK, DialogBox.DialogBoxIcon.Error);
                txtFilename.Focus();
                return;
            }
            worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                try {
                    switch(exportType) {
                        case Constants.DataType.XML:
                            ResourceGenerator.GenerateXML(outputFile, zipOutput, includeApps, includeElements, includeResources, includeTemplates, includeUsers);
                            break;
                        case Constants.DataType.XMLXLS:
                            ResourceGenerator.ExportToExcel(applicationIds, selectedLanguages, selectedBundles, zipOutput, outputFile);
                            break;
                    }
                } catch(Exception ex) {
                    dwe.Result = ex.Message;
                }
                Settings.Default.LastGenerationPath = outputFile.DirectoryName;
                Settings.Default.Save();
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                progress.Close();
                if(rwe.Result != null && rwe.Result is string) {
                    DialogBox.ShowAlert(this, rwe.Result.ToString(), "Error");
                } else {
                    DialogResult = true;
                    Close();
                }
            };
            progress = new WinProgress("Exporting...", true);
            progress.Owner = this;
            worker.RunWorkerAsync();
        }
        
    }
}
